package com.lanyou.esb.cook.proxy.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.lanyou.esb.cook.proxy.common.Constants;
import com.lanyou.esb.cook.proxy.dao.impl.BaseDao;
import com.lanyou.esb.cook.proxy.entity.IfAccTimes;
import com.lanyou.esb.cook.proxy.redis.proxy.impl.IfAccTimesJedisProxy;
import com.lanyou.esb.cook.proxy.redis.proxy.impl.IfAccTimesKeysJedisProxy;
import com.lanyou.esb.cook.proxy.redis.vo.Group;
import com.lanyou.esb.cook.proxy.redis.vo.Group.Entry;
import com.lanyou.esb.cook.proxy.redis.vo.RedisActionType;
import com.lanyou.esb.cook.proxy.service.GroupService;
import com.lanyou.esb.cook.proxy.service.IfAccTimesService;
import com.lanyou.esb.cook.proxy.service.RedisBatchService;
import com.lanyou.esb.cook.proxy.service.Service;
import com.lanyou.esb.cook.proxy.service.push.Push;

/**
 * 接口访问次数<br>
 * 描述：<br>
 * 目前接口访问次数按月进行统计
 * 
 * @author Davey.wu
 */
public class IfAccTimesServiceImpl implements IfAccTimesService,
		GroupService<IfAccTimes>, Service<IfAccTimes> {
	/** 数据库操作接口 **/
	private BaseDao<IfAccTimes> dao;
	/** 接口平均响应时间Redis操作代理 **/
	private IfAccTimesJedisProxy jedisProxy;
	/** 接口访问次数键值Redis操作代理 **/
	private IfAccTimesKeysJedisProxy ifAccTimesKeysJedisProxy;
	/** 消息推送接口 **/
	private Push<IfAccTimes> push;
	/** Redis批处理接口 **/
	private RedisBatchService redisBatchService;

	/** 时间格式：yyyyMMdd **/
	private static final SimpleDateFormat DATEFORMATE_YYYYMMDD_NOSPACE = new SimpleDateFormat(
			Constants.DATE_PATTERN_YYYYMMDD_NOSPACE);

	@Override
	public Group getGroup(IfAccTimes ifAccTimes) {
		if (ifAccTimes == null || StringUtils.isBlank(ifAccTimes.getFieldId())
				|| StringUtils.isBlank(ifAccTimes.getSystemId())
				|| StringUtils.isBlank(ifAccTimes.getIfId())
				|| ifAccTimes.getStatDate() == null) {
			return null;
		}
		// 统计时间字符串
		String statDate = getDateStr(ifAccTimes.getStatDate(),
				DATEFORMATE_YYYYMMDD_NOSPACE);
		// 键
		String key = jedisProxy.getKeyFromFields(ifAccTimes.getFieldId(),
				ifAccTimes.getSystemId(), ifAccTimes.getIfId(), statDate);
		Group group = new Group();
		// string类型条件集合
		List<Entry> strs = new ArrayList<>(1);
		// set类型条件集合
		List<Entry> sets = new ArrayList<>(1);
		group.setStrs(strs);
		group.setSets(sets);

		// 访问次数增加
		Entry entry = new Entry();
		entry.setKey(key);
		entry.setValue(1 + "");
		entry.setTimeOut(jedisProxy.getTimeOut());
		entry.setType(RedisActionType.INCR_BY);
		strs.add(entry);

		// 添加更新键
		entry = new Entry();
		entry.setKey(ifAccTimesKeysJedisProxy.getKey());
		entry.setValue(key + IfAccTimesJedisProxy.KEY_SEPARATOR
				+ ifAccTimes.getIfName());
		sets.add(entry);

		return group;
	}

	@Override
	public void pushToRedis(IfAccTimes ifAccTimes) {
		Group group = getGroup(ifAccTimes);
		if (group == null) {
			return;
		}
		try {
			// 批量将消息推送至redis
			redisBatchService.batchPush(group);
		} catch (Exception e) {
			push.putToCollection4Redis(ifAccTimes);
		}
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void save(final List<IfAccTimes> list) throws Exception {
		if (list == null || list.isEmpty()) {
			return;
		}
		try {
			TransactionTemplate tt = new TransactionTemplate(
					this.dao.getTransactionManager());
			tt.execute(new TransactionCallback() {
				public Object doInTransaction(TransactionStatus status) {
					return IfAccTimesServiceImpl.this.dao.saveAll(list);
				}
			});
		} catch (Exception e) {
			// 保留失败，将记录添加到推送队列中
			push.putToCollection4DB(list);
		}
	}

	@Override
	public void update(List<IfAccTimes> list) throws Exception {
		// 目前不存在更新业务，所以不提供实现
	}

	/**
	 * 获取日期字符串，每月的第一天
	 * 
	 * @param date
	 * @param format
	 * @return
	 */
	public static String getDateStr(Date date, SimpleDateFormat format) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		return format.format(calendar.getTime());
	}

	public IfAccTimesJedisProxy getJedisProxy() {
		return jedisProxy;
	}

	public void setJedisProxy(IfAccTimesJedisProxy jedisProxy) {
		this.jedisProxy = jedisProxy;
	}

	public IfAccTimesKeysJedisProxy getIfAccTimesKeysJedisProxy() {
		return ifAccTimesKeysJedisProxy;
	}

	public void setIfAccTimesKeysJedisProxy(
			IfAccTimesKeysJedisProxy ifAccTimesKeysJedisProxy) {
		this.ifAccTimesKeysJedisProxy = ifAccTimesKeysJedisProxy;
	}

	public BaseDao<IfAccTimes> getDao() {
		return dao;
	}

	public void setDao(BaseDao<IfAccTimes> dao) {
		this.dao = dao;
	}

	public Push<IfAccTimes> getPush() {
		return push;
	}

	public void setPush(Push<IfAccTimes> push) {
		this.push = push;
	}

	public RedisBatchService getRedisBatchService() {
		return redisBatchService;
	}

	public void setRedisBatchService(RedisBatchService redisBatchService) {
		this.redisBatchService = redisBatchService;
	}

}
